package com.igoal.utils;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTML.Tag;
import javax.swing.text.html.HTMLEditorKit.ParserCallback;
import javax.swing.text.html.parser.ParserDelegator;

public class StringUtils extends org.apache.commons.lang.StringUtils {

	public static String buildDisplayName(String userName, String firstName,
			String midleName, String lastName) {
		String result = "";
		if (StringUtils.isNotBlank(lastName)) {
			result += lastName.trim() + " ";
		}
		if (StringUtils.isNotBlank(midleName)) {
			result += midleName.trim() + " ";
		}
		if (StringUtils.isNotBlank(firstName)) {
			result += firstName.trim();
		}
		result = StringUtils.stripToNull(result);
		if (result == null) {
			result = userName;
		}

		return result;
	}

	public static String getEmailAddressPrefix(String email) {
		if (email != null && email.indexOf('@') > 0) {
			String prefix = email.substring(0, email.indexOf('@'));
			return prefix.trim();
		}
		return null;
	}

	@Deprecated
	/**
	 * using ConvertUtils instead
	 */
	public static int parseInt(String value, int ifnullValue) {
		try {
			int ret = Integer.parseInt(value);
			return ret;
		} catch (NumberFormatException ex) {
			return ifnullValue;
		}
	}

	@Deprecated
	/**
	 * using ConvertUtils instead
	 */
	public static long parseLong(String value, int ifnullValue) {
		try {
			long ret = Long.parseLong(value);
			return ret;
		} catch (NumberFormatException ex) {
			return ifnullValue;
		}
	}

	/**
	 * Standard string
	 * 
	 * @param text
	 * @return null if text is blank
	 */
	public static String removeSpacesInsideString(String text) {
		if (StringUtils.isBlank(text))
			return null;

		String[] strs = text.split(" ");
		String result = "";
		for (String str : strs) {
			if (!StringUtils.isBlank(str)) {
				result += str.trim() + " ";
			}
		}
		return result.trim();
	}

	/**
	 * Extract text but allow some tags: p, a, br, u, i, img
	 * 
	 * @param text
	 * @return
	 */
	public static String removeHTMLTags(String text) {
		if (StringUtils.isBlank(text)) {
			return null;
		}

		try {
			List<String> data = extractText(text, false);
			StringBuffer result = new StringBuffer();
			for (String str : data) {
				result.append(str);
			}
			return result.toString();
		} catch (IOException e) {
			return StringUtils.EMPTY;
		}
	}

	/**
	 * Extract text, remove all html tags
	 * 
	 * @param text
	 * @return
	 */
	public static String removeAllHTMLTags(String text) {
		if (StringUtils.isBlank(text))
			return null;

		try {
			List<String> data = extractText(text, true);
			StringBuffer result = new StringBuffer();
			for (String str : data) {
				result.append(str);
			}
			return result.toString();

		} catch (IOException e) {
			return StringUtils.EMPTY;
		}
	}

	public static boolean isContainingUnicodeOrSpecialChar(String text) {
		if (text == null)
			return false;
		boolean flag = false;
		int length = text.length();
		int code = -1;
		for (int i = 0; i < length; i++) {
			code = (int) text.charAt(i);
			if (code >= 48 && code <= 57) {
				flag = false;
			} else if (code >= 65 && code <= 90) {
				flag = false;
			} else if (code >= 97 && code <= 122) {
				flag = false;
			} else if (code == 95 || code == 45 || code == 46) {
				flag = false;
			} else {
				flag = true;
			}
			if (flag == true) {
				return flag;
			}
		}

		return false;
	}

	public static boolean hasSpaceInside(String text) {
		if (text == null)
			return false;

		int spacePos = text.trim().indexOf(" ");
		if (spacePos > 0)
			return true;

		return false;
	}

	/**
	 * Remove all html tags except for img and p. </br> Tag div will be replaced
	 * by tag br
	 * 
	 * @param html
	 * @return
	 */
	public static List<String> extractText(String html, boolean removeAllTags)
			throws IOException {
		final ArrayList<String> list = new ArrayList<String>();
		final HTML.Tag[] allowTags = new HTML.Tag[] { HTML.Tag.A, HTML.Tag.B,
				HTML.Tag.I, HTML.Tag.U, HTML.Tag.BR, HTML.Tag.IMG };
		final Map<HTML.Tag, Object> allowTagsMap = new HashMap<Tag, Object>();

		if (!removeAllTags) {
			for (HTML.Tag tag : allowTags) {
				allowTagsMap.put(tag, tag);
			}
		}

		ParserDelegator parserDelegator = new ParserDelegator();
		ParserCallback parserCallback = new ParserCallback() {
			public void handleText(final char[] data, final int pos) {
				list.add(new String(data));
			}

			public void handleStartTag(Tag tag, MutableAttributeSet attribute,
					int pos) {
				if (allowTagsMap.containsKey(tag)) {
					list.add("<" + tag.toString() + ">");
				}
			}

			public void handleEndTag(Tag t, final int pos) {
				if (Tag.DIV.equals(t) || Tag.P.equals(t)) {
					list.add(new String("<br/>"));
				}
				if (allowTagsMap.containsKey(t)) {
					list.add("</" + t.toString() + ">");
				}
			}

			public void handleSimpleTag(Tag t, MutableAttributeSet a,
					final int pos) {
				if (Tag.IMG.equals(t)) {
					String src = (String) a.getAttribute(HTML.Attribute.SRC);
					String width = (String) a
							.getAttribute(HTML.Attribute.WIDTH);
					String height = (String) a
							.getAttribute(HTML.Attribute.HEIGHT);
					list.add("<img src='" + src + "' width='" + width
							+ "' height='" + height + "'/>");
				} else if (Tag.BR.equals(t)) {
					list.add("<br>");
				}
			}

			public void handleComment(final char[] data, final int pos) {
			}

			public void handleError(final java.lang.String errMsg, final int pos) {
			}
		};

		StringReader reader = new StringReader(html);
		parserDelegator.parse(reader, parserCallback, true);
		return list;
	}

	public static String replaceUnicodeCharacters(String originalString) {
		if (isBlank(originalString))
			return EMPTY;

		originalString = originalString.trim();

		Map<Character, Character> charReplacementMap = new HashMap<Character, Character>();
		charReplacementMap.put('à', 'a');
		charReplacementMap.put('á', 'a');
		charReplacementMap.put('ạ', 'a');
		charReplacementMap.put('ả', 'a');
		charReplacementMap.put('ã', 'a');
		charReplacementMap.put('â', 'a');
		charReplacementMap.put('ầ', 'a');
		charReplacementMap.put('ấ', 'a');
		charReplacementMap.put('ậ', 'a');
		charReplacementMap.put('ẩ', 'a');
		charReplacementMap.put('ẫ', 'a');
		charReplacementMap.put('ă', 'a');
		charReplacementMap.put('ằ', 'a');
		charReplacementMap.put('ắ', 'a');
		charReplacementMap.put('ặ', 'a');
		charReplacementMap.put('ẳ', 'a');
		charReplacementMap.put('ẵ', 'a');

		charReplacementMap.put('è', 'e');
		charReplacementMap.put('é', 'e');
		charReplacementMap.put('ẹ', 'e');
		charReplacementMap.put('ẻ', 'e');
		charReplacementMap.put('ẽ', 'e');
		charReplacementMap.put('ê', 'e');
		charReplacementMap.put('ề', 'e');
		charReplacementMap.put('ế', 'e');
		charReplacementMap.put('ệ', 'e');
		charReplacementMap.put('ể', 'e');
		charReplacementMap.put('ễ', 'e');

		charReplacementMap.put('ì', 'i');
		charReplacementMap.put('í', 'i');
		charReplacementMap.put('ị', 'i');
		charReplacementMap.put('ỉ', 'i');
		charReplacementMap.put('ĩ', 'i');

		charReplacementMap.put('ò', 'o');
		charReplacementMap.put('ó', 'o');
		charReplacementMap.put('ọ', 'o');
		charReplacementMap.put('ỏ', 'o');
		charReplacementMap.put('õ', 'o');
		charReplacementMap.put('ô', 'o');
		charReplacementMap.put('ồ', 'o');
		charReplacementMap.put('ố', 'o');
		charReplacementMap.put('ộ', 'o');
		charReplacementMap.put('ổ', 'o');
		charReplacementMap.put('ỗ', 'o');
		charReplacementMap.put('ơ', 'o');
		charReplacementMap.put('ờ', 'o');
		charReplacementMap.put('ớ', 'o');
		charReplacementMap.put('ợ', 'o');
		charReplacementMap.put('ở', 'o');
		charReplacementMap.put('ỡ', 'o');

		charReplacementMap.put('ù', 'u');
		charReplacementMap.put('ú', 'u');
		charReplacementMap.put('ụ', 'u');
		charReplacementMap.put('ủ', 'u');
		charReplacementMap.put('ũ', 'u');
		charReplacementMap.put('ư', 'u');
		charReplacementMap.put('ừ', 'u');
		charReplacementMap.put('ứ', 'u');
		charReplacementMap.put('ự', 'u');
		charReplacementMap.put('ử', 'u');
		charReplacementMap.put('ữ', 'u');

		charReplacementMap.put('ỳ', 'y');
		charReplacementMap.put('ý', 'y');
		charReplacementMap.put('ỵ', 'y');
		charReplacementMap.put('ỷ', 'y');
		charReplacementMap.put('ỹ', 'y');

		charReplacementMap.put('đ', 'd');

		StringBuilder builder = new StringBuilder();

		for (char currentChar : originalString.toCharArray()) {
			Character replacementChar = charReplacementMap.get(currentChar);
			builder.append(replacementChar != null ? replacementChar
					: currentChar);
		}

		String newString = builder.toString();

		return newString;
	}

	public static String removeSpecialCharacters(String str) {
		String specialChars = "!?<>.@#$%^&*()=+{}[]|~`’‘'\",_";
		Map<Integer, String> specialCharsMap = new HashMap<Integer, String>();

		for (char currentChar : specialChars.toCharArray()) {
			specialCharsMap.put((int) currentChar, "");
		}

		specialCharsMap.put((int) ' ', "-");

		StringBuilder sb = new StringBuilder();

		for (char currentChar : str.toCharArray()) {
			String replacement = specialCharsMap.get((int) currentChar);
			sb.append(replacement == null ? currentChar : replacement);
		}

		return sb.toString();
	}

	public static String convertToSEOLink(String link) {
		if (StringUtils.isBlank(link)) {
			return null;
		}

		link = link.toLowerCase().trim();
		link = replaceUnicodeCharacters(link);
		link = removeSpecialCharacters(link);

		return link;
	}

	/**
	 * isEmailValid: Validate email address using Java reg ex. This method
	 * checks if the input string is a valid email address.
	 * 
	 * @param email
	 *            String. Email address to validate
	 * @return boolean: true if email address is valid, false otherwise.
	 */
	public static boolean isEmailValid(String email) {
		boolean isValid = false;

		/*
		 * Email format: A valid email address will have following format:
		 * [\\w\\.-]+: Begins with word characters, (may include periods and
		 * hypens).
		 * 
		 * @: It must have a '@' symbol after initial characters.
		 * ([\\w\\-]+\\.)+: '@' must follow by more alphanumeric characters (may
		 * include hypens.). This part must also have a "." to separate domain
		 * and subdomain names. [A-Z]{2,4}$ : Must end with two to four
		 * alaphabets. (This will allow domain names with 2, 3 and 4 characters
		 * e.g pa, com, net, wxyz)
		 * 
		 * Examples: Following email addresses will pass validation abc@xyz.net;
		 * ab.c@tx.gov
		 */

		// Initialize reg ex for email.
		String expression = "^[\\w\\.-]+@([\\w\\-]+\\.)+[A-Z]{2,4}$";
		CharSequence inputStr = email;
		// Make the comparison case-insensitive.
		Pattern pattern = Pattern.compile(expression, Pattern.CASE_INSENSITIVE);
		Matcher matcher = pattern.matcher(inputStr);
		if (matcher.matches()) {
			isValid = true;
		}
		return isValid;
	}
	
	/**
	 * without using reg
	 * @param str
	 * @param findStr
	 * @param replaceStr
	 * @return
	 */
	public static String replaceAll(String str, String findStr, String replaceStr){
		if(isNotBlank(str) || isNotBlank(findStr) || isNotBlank(replaceStr) 
				|| findStr.trim().equalsIgnoreCase(replaceStr.trim())){
			return null;
		}
		
		while(str.indexOf(findStr) >= 0){
			int pos = str.indexOf(findStr);
			str = str.substring(0, pos) + replaceStr + str.substring(pos, str.length()-1);
		}
		
		return str;
	}

}
